package org.jvm.instruction.references;

import org.jvm.instruction.base.Index8Instruction;
import org.jvm.rtda.Object;
import org.jvm.rtda.heap.Klass;
import org.jvm.rtda.heap.stringpool.StringPool;
import org.jvm.rtda.heap.symref.ClassRef;
import org.jvm.rtda.thread.*;

/**
 * 从常量池中获取常量值，压操作数栈
 *
 * @author 海燕
 * @date 2023/2/7
 */
public class LDC extends Index8Instruction {

    @Override
    public void execute(Frame frame) {
        exe(frame, this.index);
    }

    public static void exe(Frame frame, int index) {
        java.lang.Object constant = frame.getMethod().getKlass().getConstantPool().getConstant(index);
        OperandStack operandStack = frame.getOperandStack();
        if (constant instanceof Integer) {
            operandStack.pushInt((Integer) constant);
        } else if (constant instanceof Float) {
            operandStack.pushFloat((Float) constant);
        } else if (constant instanceof String) {
            Object jString = StringPool.jString((String) constant);
            operandStack.pushRef(jString);
        }
        /**
         * 虽然常量池中是类引用标识ClassRef，但ClassRef并不是一个Java实例
         * 应当压操作数栈的是类对应的类对象实例
         * 形如这种语句会触发LDC的类对象压栈 Class string = java.lang.String.class;
         */
        else if (constant instanceof ClassRef) {
            Klass resolvedClass = ((ClassRef) constant).resolvedClass(frame.getThread());
            operandStack.pushRef(resolvedClass.getjClass());
        } else {
            throw new RuntimeException("unknow constant");
        }
    }
}
